﻿namespace NTLib.Pipe.Network.Connectors
{
    using NTLib.Core.Args;
    using NTLib.Core.Component;
    using NTLib.Pipe.Network.Descriptors;
    using Streaming.Containers;
    using Streaming.Descriptors.Packages;
    using System;
    using System.Threading;
    using System.Threading.Tasks;

    /// <summary>
    /// Manage the connection
    /// </summary>
    public interface IConnector : IComponent, IDisposable
    {
        #region Properties

        /// <summary>
        /// Gets the address.
        /// </summary>
        INetworkAddress Address { get; }

        /// <summary>
        /// Gets a value indicating whether this <see cref="IConnector"/> is connected.
        /// </summary>
        /// <value>
        ///   <c>true</c> if connected; otherwise, <c>false</c>.
        /// </value>
        ConnectionStatus Connected { get; }

        /// <summary>
        /// Gets a value indicating whether this instance is initialized.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance is initialized; otherwise, <c>false</c>.
        /// </value>
        bool IsInitialized { get; }

        /// <summary>
        /// Gets a value indicating whether this instance can pop item.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance can pop item; otherwise, <c>false</c>.
        /// </value>
        bool CanPopItem { get; }

        /// <summary>
        /// Gets the value indicating that the current pipe allow the user to push items through it.
        /// </summary>
        /// <value>
        /// <c>true</c> if this instance can push item; otherwise, <c>false</c>.
        /// </value>
        bool CanPushItem { get; }

        #endregion

        #region Event

        /// <summary>
        /// Raised when The connection changed.
        /// </summary>
        event EventHandler<ValueChangedEventArgs<ConnectionStatus>> ConnectionChanged;

        #endregion

        #region Methods

        /// <summary>
        /// Initializes the connector.
        /// </summary>
        /// <param name="isHost">if set to <c>true</c> [is host].</param>
        Task InitializeAsync(bool isHost = false);

        /// <summary>
        /// Connects the connector.
        /// </summary>
        Task ConnectAsync(INetworkAddress address, CancellationToken token = default(CancellationToken));

        /// <summary>
        /// Asynchroniously read data
        /// </summary>
        Task<IPackage> ReadAsync(IPackageDescriptor desc, CancellationToken token = default(CancellationToken));

        /// <summary>
        /// Asynchroniously send data
        /// </summary>
        Task SendAsync(IPackage pkg, CancellationToken token = default(CancellationToken));

        /// <summary>
        /// Closes the connector.
        /// </summary>
        Task CloseAsync(CancellationToken token = default(CancellationToken));

        #endregion
    }
}
